#include "stdafx.h"
#include "Logger.h"

//////////////////////////////////////////////////////////////////////////

ConsoleLogger::ConsoleLogger()
:m_loglist(140), m_inputHistory(20), m_onelineHeight(0.05), m_pagelinecount(35)
{
	m_InputUpdated			= true;
	m_Active				= false;
	m_Visibled				= true;
	m_KeyUpdated			= false;
	m_CursorBlinkOn			= false;

	m_BackDeleteDelay		= 0.1f;
	m_beforeBackDelete		= 0.0f;


	m_currEndline			= 0;
	m_extendInputline		= 0;

	m_curInputidx			= 0;
	m_cursorPos				= 0;

	m_printText = OverlayManager::getSingleton().createOverlayElement("TextArea", "PrintText");
	m_printText->setCaption("*** start console... ***");
	m_printText->setMetricsMode(GMM_RELATIVE);
	m_printText->setPosition(0, 0);
	m_printText->setParameter("font_name", "Console");
	m_printText->setParameter("colour_top", "1 1 1");
	m_printText->setParameter("colour_bottom","1 1 1");
	m_printText->setParameter("char_height", "0.025");

	m_inputText = OverlayManager::getSingleton().createOverlayElement("TextArea", "InputText");
	m_inputText->setCaption(">");
	m_inputText->setMetricsMode(GMM_RELATIVE);
	m_inputText->setPosition(0.0f, 0.97f);
	m_inputText->setParameter("font_name", "Console");
	m_inputText->setParameter("colour_top", "1 1 1");
	m_inputText->setParameter("colour_bottom","1 1 1");
	m_inputText->setParameter("char_height", "0.025");

	// Key Registry
	m_Keymap.insert(std::make_pair((uint)OIS::KC_A, 'a'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_B, 'b'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_C, 'c'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_D, 'd'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_E, 'e'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_F, 'f'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_G, 'g'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_H, 'h'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_I, 'i'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_J, 'j'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_K, 'k'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_L, 'l'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_M, 'm'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_N, 'n'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_O, 'o'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_P, 'p'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_Q, 'q'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_R, 'r'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_S, 's'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_T, 't'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_U, 'u'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_V, 'v'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_W, 'w'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_X, 'x'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_Y, 'y'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_Z, 'z'));

	m_Keymap.insert(std::make_pair((uint)OIS::KC_1, '1'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_2, '2'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_3, '3'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_4, '4'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_5, '5'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_6, '6'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_7, '7'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_8, '8'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_9, '9'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_0, '0'));

	m_Keymap.insert(std::make_pair((uint)OIS::KC_COMMA, ','));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_PERIOD, '.'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_SLASH, '/'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_SEMICOLON, ';'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_APOSTROPHE, '\''));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_LBRACKET, '['));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_RBRACKET, ']'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_MINUS, '-'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_EQUALS, '='));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_BACKSLASH, '\\'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_GRAVE, '`'));

	m_Keymap.insert(std::make_pair((uint)OIS::KC_SPACE, ' '));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_DIVIDE, '/'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_MULTIPLY, '*'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_SUBTRACT, '-'));
	m_Keymap.insert(std::make_pair((uint)OIS::KC_ADD, '+'));

	//Shift Key Registry
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_A, 'A'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_B, 'B'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_C, 'C'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_D, 'D'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_E, 'E'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_F, 'F'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_G, 'G'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_H, 'H'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_I, 'I'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_J, 'J'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_K, 'K'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_L, 'L'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_M, 'M'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_N, 'N'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_O, 'O'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_P, 'P'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_Q, 'Q'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_R, 'R'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_S, 'S'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_T, 'T'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_U, 'U'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_V, 'V'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_W, 'W'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_X, 'X'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_Y, 'U'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_Z, 'Z'));

	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_1, '!'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_2, '@'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_3, '#'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_4, '$'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_5, '%'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_6, '^'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_7, '&'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_8, '*'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_9, '('));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_0, ')'));

	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_COMMA, '<'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_PERIOD, '>'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_SLASH, '?'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_SEMICOLON, ':'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_APOSTROPHE, '"'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_LBRACKET, '{'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_RBRACKET, '}'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_MINUS, '_'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_EQUALS, '+'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_BACKSLASH, '|'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_GRAVE, '~'));

	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_SPACE, ' '));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_DIVIDE, '/'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_MULTIPLY, '*'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_SUBTRACT, '-'));
	m_ShiftKeymap.insert(std::make_pair((uint)OIS::KC_ADD, '+'));
}

ConsoleLogger::~ConsoleLogger()
{
}

void ConsoleLogger::Init()
{
	if (m_Active)
		return;

	m_root				= g_App->GetRoot();
	m_logSceneManager	= m_root->getSceneManagerIterator().getNext();

	m_logNode			= m_logSceneManager->getRootSceneNode()->createChildSceneNode("#ConsoleLogger");

	m_printArea			= new Rectangle2D(true);
	m_printArea->setCorners(-1, 1, 1, -0.75);
	m_printArea->setMaterial("console/background");
	m_printArea->setRenderQueueGroup(RENDER_QUEUE_OVERLAY);
	m_printArea->setBoundingBox(AxisAlignedBox(-100000.0 * Vector3::UNIT_SCALE, 100000.0 * Vector3::UNIT_SCALE));
	m_logNode->attachObject(m_printArea);

	m_inputArea			= new Rectangle2D(true);
	m_inputArea->setCorners(-1, -0.94, 1, -1);
	m_inputArea->setMaterial("console/background");
	m_inputArea->setRenderQueueGroup(RENDER_QUEUE_OVERLAY);
	m_inputArea->setBoundingBox(AxisAlignedBox(-100000.0 * Vector3::UNIT_SCALE, 100000.0 * Vector3::UNIT_SCALE));
	m_logNode->attachObject(m_inputArea);

	m_inputText->setPosition(0.0f, 0.97f);

	m_overlay = OverlayManager::getSingleton().create("Console");
	m_overlay->add2D((OverlayContainer*)m_printText);
	m_overlay->add2D((OverlayContainer*)m_inputText);
	m_overlay->show();

	m_Active = true;

	m_printButtom		= -0.75f;
	m_inputTop			= -0.94f;

	m_extendInputline	= 0;
	m_CursorTime		= 0.3f;

	m_inputlist.push_back(String(""));
	m_curInputiter		= m_inputlist.begin();
	m_curInputidx		= 0;

#ifndef _DEBUG
	SetVisible(false);
#endif
}

void ConsoleLogger::Shutdown()
{
	if (!m_Active)
		return;

	if (m_overlay)
	{
		m_inputText->setCaption("> ");
		m_printText->setCaption("");

		OverlayManager::getSingleton().destroy(m_overlay);
		m_overlay = NULL;
	}

	m_Active = false;
}

void ConsoleLogger::Write(const char* format, va_list arg)
{
	char buf[MAX_LOGBUFFER_SIZE];

	int size = vsnprintf(buf, sizeof(buf), format, arg);
	buf[sizeof(buf)-1] = 0;

	if (g_Log->IsFilter(buf, size))
		return;

	StringList	m_writelist;
	String		m_writestr;

	for (int count = 0; count <= size; ++count)
	{
		if (buf[count] != '\n')
		{
			m_writestr += buf[count];
		}

		if (buf[count] == '\n' || count == size)
		{
			if (buf[count] == '\n' && count + 1 == size)
				continue;

			m_loglist.push_back(m_writestr);
			m_writestr = "";
		}
	}

	StringList::iterator iter = m_writelist.begin();
	while(iter != m_writelist.end())
	{
		if (m_loglist.full())
			m_loglist.pop_front();

		m_loglist.push_back(*iter);
	}

	m_currEndline = m_loglist.size();
}

#ifdef _WIN32
void ConsoleLogger::CopyToClipboard()
{
	if (!IsClipboardFormatAvailable(CF_TEXT))
		return;
	
	HWND hwnd;
	g_App->GetRenderWindow()->getCustomAttribute("WINDOW",(void*)&hwnd);
	OpenClipboard(hwnd);
	
	HGLOBAL hmem = GetClipboardData(CF_TEXT);
	String clipstr = (char*)GlobalLock(hmem);
	
	GlobalUnlock(hmem);
	CloseClipboard();

	StringList cliplist;
	String curstr = "";

	int appendidx = 0;
	for (int curstridx = 0; curstridx < (int)clipstr.length(); ++curstridx)
	{
		char appendchar = clipstr.at(curstridx);
		
		if (appendchar < 0)	
			return;

		if (appendchar != '\n')
			curstr += clipstr.at(curstridx);

		if (appendchar == '\n' || curstridx - appendidx > 105 || 
			curstridx + 1 == clipstr.length())
		{
			cliplist.push_back(curstr);
			curstr = "";
			appendidx = curstridx;
		}
	}

	if (m_inputlist.size() + cliplist.size() < 20)
	{
		StringList::iterator clipiter = m_curInputiter;
		clipiter++;

		int clipsize = cliplist.size();
		m_inputlist.splice(clipiter, cliplist);
		
		if (*m_curInputiter == "")
		{
			m_inputlist.erase(m_curInputiter);
			clipsize--;
		}

		m_curInputidx += clipsize;
		m_curInputiter = m_inputlist.begin();
		for (int i = 0; i < m_curInputidx; i++)
			m_curInputiter++;

		m_cursorPos = m_curInputiter->length();

		m_extendInputline = m_inputlist.size() - 1;
		if (m_extendInputline > 10)
			m_extendInputline = 10;
	}
}
#endif

void ConsoleLogger::InputUpdate(InputKeyEvent* evt)
{
	if (!m_Visibled)
		return;
	
	bool isSpecialKey = false;

	if (evt->IsTriggered(OIS::KC_RETURN))
	{
		isSpecialKey = true;

		if (evt->IsModifier(OIS::Keyboard::Shift))
		{
			if(m_extendInputline < 10)
				m_extendInputline++;

			if (m_inputlist.size() < 20)
			{
				String tailstr;
				if (m_cursorPos < (int)m_curInputiter->length())
				{
					tailstr = m_curInputiter->substr(m_cursorPos);	
					m_curInputiter->resize(m_cursorPos);
				}

				m_curInputiter = m_inputlist.insert(++m_curInputiter, tailstr);
				
				m_curInputidx++;
				m_cursorPos = 0;
			}
		}
		else
		{
			String popinput = "> ";

			StringList::iterator iter = m_inputlist.begin();
			while (iter != m_inputlist.end())
			{
				if (m_loglist.full())
					m_loglist.pop_front();

				popinput += *iter;
				m_loglist.push_back(popinput);
				popinput = "";
				iter++;
			}
			
			if (m_inputHistory.size() > 20)
				m_inputHistory.pop_front();

			m_inputHistory.push_front(m_inputlist);

			m_inputlist.clear();
			m_inputlist.push_back(String(""));
			m_curInputiter = m_inputlist.begin();

			m_currEndline		= m_loglist.size();
			m_extendInputline	= 0;
			m_curInputidx		= 0;
			m_cursorPos			= 0;
			m_historyidx		= 0;
		}
	}
	
	if (evt->IsTriggered(OIS::KC_PGUP) && m_loglist.size() > m_pagelinecount)
	{
		if (m_currEndline - m_pagelinecount > m_pagelinecount)
			m_currEndline -= m_pagelinecount;
		else
			m_currEndline = m_pagelinecount;

		isSpecialKey = true;
	}

	if (evt->IsTriggered(OIS::KC_PGDOWN) && m_loglist.size() > m_pagelinecount)
	{
		if (m_currEndline + m_pagelinecount < m_loglist.size())
			m_currEndline += m_pagelinecount;
		else
			m_currEndline = m_loglist.size();

		isSpecialKey = true;
	}
	
	// MoveCursor
	if (evt->IsPressed(OIS::KC_LEFT) || evt->IsTriggered(OIS::KC_LEFT))
	{
		isSpecialKey = true;

		bool result = false;
		if (evt->IsTriggered(OIS::KC_LEFT))
		{
			result = true;
		}
		else if(UpdateDelayKeyTime())
		{
			result = true;
		}

		if (result)
		{
			if (m_cursorPos > 0)
				m_cursorPos--;

			m_CursorTime = 0.3f;
			m_CursorBlinkOn = true;
		}
	}

	if (evt->IsPressed(OIS::KC_RIGHT) || evt->IsTriggered(OIS::KC_RIGHT))
	{
		isSpecialKey = true;

		bool result = false;
		if (evt->IsTriggered(OIS::KC_RIGHT))
		{
			result = true;
		}
		else if(UpdateDelayKeyTime())
		{
			result = true;
		}

		if (result)
		{
			if (m_cursorPos < (int)m_curInputiter->length())
				m_cursorPos++;

			m_CursorTime = 0.3f;
			m_CursorBlinkOn = true;
		}
	}

	if ((evt->IsPressed(OIS::KC_UP) || evt->IsTriggered(OIS::KC_UP))
		&& m_curInputidx > 0)
	{
		isSpecialKey = true;

		bool result = false;
		if (evt->IsTriggered(OIS::KC_UP))
		{
			result = true;
		}
		else if(UpdateDelayKeyTime())
		{
			result = true;
		}

		if (result)
		{
			isSpecialKey = true;

			m_curInputidx--;
			m_curInputiter--;
			
			int strlength = m_curInputiter->length();
			if (m_cursorPos > strlength - 1)
				m_cursorPos = strlength - 1;

			if (m_cursorPos < 0)
				m_cursorPos = 0;

			m_CursorTime = 0.3f;
			m_CursorBlinkOn = true;
		}
	}

	if ((evt->IsPressed(OIS::KC_DOWN) || evt->IsTriggered(OIS::KC_DOWN))
		&& m_curInputidx < (int)(m_inputlist.size() - 1))
	{
		isSpecialKey = true;

		bool result = false;
		if (evt->IsTriggered(OIS::KC_DOWN))
		{
			result = true;
		}
		else if(UpdateDelayKeyTime())
		{
			result = true;
		}
		
		if (result)
		{
			m_curInputidx++;
			m_curInputiter++;

			int strlength = m_curInputiter->length();
			if (m_cursorPos > strlength - 1)
				m_cursorPos = strlength - 1;

			if (m_cursorPos < 0)
				m_cursorPos = 0;

			m_CursorTime = 0.3f;
			m_CursorBlinkOn = true;
		}
	}

	if (evt->IsTriggered(OIS::KC_HOME))
	{
		isSpecialKey = true;

		if (evt->IsModifier(OIS::Keyboard::Shift))
		{
			m_curInputiter = m_inputlist.begin();	
			m_curInputidx = 0;
		}

		m_cursorPos = 0;
	}

	if (evt->IsTriggered(OIS::KC_END))
	{
		isSpecialKey = true;

		if (evt->IsModifier(OIS::Keyboard::Shift))
		{
			m_curInputiter = --m_inputlist.end();
			m_curInputidx = m_inputlist.size() - 1;
		}

		m_cursorPos = m_curInputiter->length();
		
	}
	//////////////////////////////////////////////////////////////////////////

#ifdef _WIN32
	if (evt->IsTriggered(OIS::KC_V) && evt->IsModifier(OIS::Keyboard::Ctrl))
	{
		isSpecialKey = true;

		CopyToClipboard();
	}
#endif
	//////////////////////////////////////////////////////////////////////////

	// History
	if (evt->IsTriggered(OIS::KC_UP) && evt->IsModifier(OIS::Keyboard::Shift))
	{
		isSpecialKey = true;

		if (m_inputHistory.size() > 0 && m_historyidx < m_inputHistory.size())
		{
			m_inputlist = m_inputHistory[m_historyidx++];
			
			m_curInputiter = m_inputlist.begin();
			m_cursorPos = 0;
			m_curInputidx = 0;
			
			m_extendInputline = m_inputlist.size() - 1;
			if (m_extendInputline > 10)
				m_extendInputline = 10;

			ChangedInputConsole();
		}
	}

	if (evt->IsTriggered(OIS::KC_DOWN) && evt->IsModifier(OIS::Keyboard::Shift))
	{
		isSpecialKey = true;

		if (m_inputHistory.size() > 0 && m_historyidx > 0)
		{
			m_inputlist = m_inputHistory[--m_historyidx];

			m_curInputiter = m_inputlist.begin();
			m_cursorPos = 0;
			m_curInputidx = 0;

			m_extendInputline = m_inputlist.size() - 1;
			if (m_extendInputline > 10)
				m_extendInputline = 10;

			ChangedInputConsole();
		}
	}
	//////////////////////////////////////////////////////////////////////////

	if (evt->IsPressed(OIS::KC_BACK) || evt->IsTriggered(OIS::KC_BACK))
	{
		isSpecialKey = true;

		bool deleted = false;
		if (evt->IsTriggered(OIS::KC_BACK))
		{
			deleted = true;
		}
		else if (UpdateDelayKeyTime())
		{
			deleted = true;
		}

		if (deleted)
		{
			if (m_curInputiter->length() == 0 && m_curInputidx > 0)
			{
				m_curInputidx--;
				StringList::iterator eraseiter = m_curInputiter;
				m_curInputiter = --m_curInputiter;
				m_inputlist.erase(eraseiter);

				if(m_curInputidx >= 10)
				{
					m_extendInputline = 10;
				}
				else if (m_extendInputline > 0)
				{
					m_extendInputline--;
				}
				
				ChangedInputConsole();
				m_cursorPos = m_curInputiter->size();
			}
			
			if (m_cursorPos > 0)
			{
				String str = *m_curInputiter;
				str = str.erase(m_cursorPos - 1, 1);
				*m_curInputiter = str;

				m_cursorPos--;
			}
		}
	}

	if (evt->IsPressed(OIS::KC_DELETE) || evt->IsTriggered(OIS::KC_DELETE))
	{
		isSpecialKey = true;

		bool deleted = false;
		if (evt->IsTriggered(OIS::KC_DELETE))
		{
			deleted = true;
		}
		else if (UpdateDelayKeyTime())
		{
			deleted = true;
		}

		if (deleted)
		{
			bool linedelete = false;
			if (m_curInputiter->length() == 0 && m_curInputidx > 0)
			{
				StringList::iterator eraseiter = m_curInputiter;
				m_curInputiter = --m_curInputiter;
				m_curInputidx--;

				m_inputlist.erase(eraseiter);

				if (m_curInputidx >= 10)
				{
					m_extendInputline = 10;
				}
				else if (m_extendInputline > 0)
				{
					m_extendInputline--;
				}

				ChangedInputConsole();
				m_cursorPos = m_curInputiter->size();
				linedelete = true;
			}

			if (!linedelete && m_cursorPos >= 0 && m_curInputiter->length() > 0)
			{
				if ((int)m_curInputiter->length() > m_cursorPos)
				{
					String str = *m_curInputiter;
					str = str.erase(m_cursorPos, 1);
					*m_curInputiter = str;
				}
				else if(m_curInputidx < (int)m_inputlist.size() - 1)
				{
					int mergeline = 105 - m_curInputiter->length();
					
					StringList::iterator mergeiter = m_curInputiter;
					mergeiter++;

					String mergestr;
					if ((int)mergeiter->length() > mergeline)
					{
						mergestr = *mergeiter;
						mergestr.resize(mergeline);

						*mergeiter = mergeiter->substr(mergeline);
					}
					else
					{
						mergestr = *mergeiter;

						m_inputlist.erase(mergeiter);

						if (m_inputlist.size() < 11)
							m_extendInputline = m_inputlist.size() - 1;

						ChangedInputConsole();
					}

					*m_curInputiter += mergestr;
				}
			}
		}
	}

	if (!isSpecialKey)
	{
		KeyMap::iterator iter;
		KeyMap::iterator enditer;
		if (evt->IsModifier(OIS::Keyboard::Shift) || evt->IsCapsLock())
		{
			iter	= m_ShiftKeymap.begin();
			enditer = m_ShiftKeymap.end();
		}
		else
		{
			iter	= m_Keymap.begin();
			enditer = m_Keymap.end();
		}

		while (iter != enditer)
		{
			if ((evt->IsTriggered((OIS::KeyCode)iter->first) ||
				evt->IsRepeated((OIS::KeyCode)iter->first)) &&
				(m_inputlist.size() <= 20 && m_curInputiter->length() < 106))
			{	
				m_curInputiter->insert(m_cursorPos++, 1, iter->second);
			}

			iter++;
		}

		if (m_curInputiter->size() >= 106 && m_inputlist.size() < 20)
			createLine(m_curInputiter);

		ClearDelayKeyTime();
	}

	m_KeyUpdated = true;
}

void ConsoleLogger::createLine(StringList::iterator nextiter)
{
	String newstr = nextiter->substr(105);
	nextiter->resize(105);

	StringList::iterator nextlineiter = nextiter;
	nextlineiter++;

	if (nextlineiter == m_inputlist.end())
	{
		if(m_extendInputline < 10)
			m_extendInputline++;

		m_inputlist.push_back(String(newstr));

		if (m_curInputidx == m_inputlist.size() - 2 && m_cursorPos > 105)
		{
			m_curInputidx++;
			m_cursorPos = 1;
			m_curInputiter = --m_inputlist.end();
		}
	}
	else
	{
		*nextlineiter = newstr + *nextlineiter;
		if (nextlineiter->length() >= 106)
			createLine(nextlineiter);

		if (m_cursorPos > 105)
		{
			m_curInputidx++;
			m_cursorPos = 1;
			m_curInputiter++;
		}
	}

	ChangedInputConsole();
}

void ConsoleLogger::ConsoleUpdate(FrameUpdatedEvent* evt)
{
	if (!m_KeyUpdated)
		return;
	
	float extendMove	= ((float)m_extendInputline * m_onelineHeight);

	m_inputArea->setCorners(-1, -0.94f + extendMove, 1, -1);
	m_printArea->setCorners(-1, 1, 1, -0.75f + extendMove);
	m_inputText->setPosition(0.0f, 0.97f - (float)m_extendInputline * 0.025f);

	m_CursorTime -= evt->DT;
	if (m_CursorTime < 0.0f)
	{
		m_CursorTime = 0.3f;
		m_CursorBlinkOn = !m_CursorBlinkOn;
	}

	// input line
	String inputline = "> ";
	uint passCount = m_curInputidx > 10 ? m_curInputidx - 10 : 0;

	uint count = 0;
	StringList::iterator iter = m_inputlist.begin();
	while (iter != m_inputlist.end())
	{
		if ((passCount > 0 && passCount <= count) || passCount == 0)	
		{
			String appendstr = *iter;
			if ( m_curInputidx == count && (m_CursorBlinkOn && appendstr.size() >= 0))
			{
				appendstr.replace(m_cursorPos, 1, 1, '_');
			}
	
			inputline += appendstr + "\n";
		}

		iter++;
		count++;
	}

	m_inputText->setCaption(inputline);

	// log line
	String logline;
	int logstart = 0, logend = m_currEndline;
	
	if (logend - (m_pagelinecount - m_extendInputline) > 0)
		logstart = logend - (m_pagelinecount - m_extendInputline);
	
	for (int count = logstart; count < logend; ++count)
	{
		logline += m_loglist[count] + "\n";
	}

	m_printText->setCaption(logline);

	m_KeyUpdated = false;
}

bool ConsoleLogger::IsVisible()
{
	return m_Visibled;
}

void ConsoleLogger::SetVisible(bool visible)
{
	m_Visibled = visible;

	if (m_Visibled)
	{
		m_printArea->setVisible(true);	
		m_inputArea->setVisible(true);

		m_printText->show();
		m_inputText->show();
	}
	else
	{
		m_printArea->setVisible(false);	
		m_inputArea->setVisible(false);

		m_printText->hide();
		m_inputText->hide();
	}
}

void ConsoleLogger::ChangedInputConsole()
{
	m_inputArea->setCorners(-1, -0.94f + (float)m_extendInputline * m_onelineHeight, 1, -1);
	m_inputText->setPosition(0.0f, 0.97f - (float)m_extendInputline * 0.025f);	
}

bool ConsoleLogger::UpdateDelayKeyTime()
{
	if (m_beforeBackDelete == 0.0f)
	{
		m_beforeBackDelete = g_Clock->getMillisecondsCPU() / 1000.0f;
		return false;
	}

	float t = g_Clock->getMillisecondsCPU() / 1000.0f;
	m_BackDeleteDelay -= t - m_beforeBackDelete;
	m_beforeBackDelete = t;

	if (m_BackDeleteDelay <= 0.0f)
	{	
		m_BackDeleteDelay = 0.1f;
		return true;
	}

	return false;
}

void ConsoleLogger::ClearDelayKeyTime()
{
	m_BackDeleteDelay = 0.1f;
	m_beforeBackDelete = 0.0f;	
}